// 数字示例

// 将示例代码封装在一个函数中
pub fn run_examples() {
  println!("===== Rust 整数示例 =====\n");

  // 1. 数字类型定义及基础使用
  println!("1. 数字类型定义及基础使用:");
  example_1();

  // 2. 类型判定及打印, 类型强转
  println!("2. 类型判定及打印, 类型强转:");
  example_2();
  
  // 3. 数字溢出处理
  println!("3. 数字溢出处理:");
  example_3();
}

// 1. 数字类型定义及基础使用
fn example_1() {
  let x = 32;
  let y = 32_u8;
  let z: u64 = 100_000_000_000;
  println!("   定义 let x = 100_000_000_000, equal to {}", x);
  println!("   定义 let x = 32; equal to {}", y);
  println!("   定义 let z: u64 = 100_000_000_000; equal to {}; 这叫数字分割", z);
}

// 2. 类型判定及打印, 类型强转
fn example_2() {
  let x = 5;
  assert_eq!("u32".to_string(), type_of(&(x as u32)));
  println!("    type_of x = '{}'", type_of(&(x as u32)))
}

// 以下函数可以获取传入参数的类型，并返回类型的字符串形式，例如  "i8", "u8", "i32", "u32"
fn type_of<T>(_: &T) -> String {
  format!("{}", std::any::type_name::<T>())
}

// 3. 数字溢出处理
fn example_3() {
  let a : u8 = 255;
  // 使用包装加法（溢出时环绕）
  println!("    a=255_u8, a.wrapping_add(20) = {}", a.wrapping_add(20));
  // 使用 overflowing_* 方法返回该值和一个指示是否存在溢出的布尔值
  let (b, is_overflow) = a.overflowing_add(20);
  println!("    a=255_u8, a.overflowing_add(20) = {}, is_overflow = {}", b, is_overflow);
  // 使用 saturating_* 方法可以限定计算后的结果不超过目标类型的最大值或低于最小值
  println!("    a=255_u8, a.saturating_add(20) = {}", a.saturating_add(20));
  // 使用 checked_add 可以返回一个 Option 类型，当发生溢出时返回 None
  let v2 = match a.checked_add(20) {
    Some(result) => result,
    None => 0
  };
  println!("    a=255_u8, match a.checked_add(20) = {}", v2);
  
}